package com.rbac.modules.system.controller;

import java.util.List;

import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.rbac.common.utils.R;
import com.rbac.modules.system.dto.AssignPermissionDTO;
import com.rbac.modules.system.dto.AssignUserDTO;
import com.rbac.modules.system.dto.RoleDTO;
import com.rbac.modules.system.dto.RoleQuery;
import com.rbac.modules.system.entity.Role;
import com.rbac.modules.system.entity.SysPermission;
import com.rbac.modules.system.service.RoleService;
import com.rbac.modules.system.service.SysPermissionService;

import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;

@Tag(name = "系统管理-角色管理", description = "角色管理相关接口")
@RestController
@RequestMapping("system/roles")
public class RoleController {

    @Resource
    private RoleService roleService;

    @Resource
    private SysPermissionService permissionService;

    @Operation(summary = "分页查询角色列表", description = "根据条件分页查询角色列表")
    @GetMapping("/page")
    @SaCheckPermission(value = "system:role:list", orRole = "admin")
    public R<Page<Role>> page(
            @Parameter(description = "角色名称") @RequestParam(required = false) String roleName,
            @Parameter(description = "角色编码") @RequestParam(required = false) String roleCode,
            @Parameter(description = "状态（0：禁用，1：启用）") @RequestParam(required = false) Integer status,
            @Parameter(description = "当前页码") @RequestParam(defaultValue = "1") Integer current,
            @Parameter(description = "每页条数") @RequestParam(defaultValue = "10") Integer size,
            @Parameter(description = "排序字段") @RequestParam(required = false) String orderField,
            @Parameter(description = "排序方式（asc：升序，desc：降序）") @RequestParam(required = false) String orderType) {
        RoleQuery query = new RoleQuery();
        query.setRoleName(roleName);
        query.setRoleCode(roleCode);
        query.setStatus(status);
        query.setCurrent(current);
        query.setSize(size);
        query.setOrderField(orderField);
        query.setOrderType(orderType);
        return R.ok(roleService.page(query));
    }

    @Operation(summary = "创建角色", description = "创建新的角色")
    @PostMapping
    @SaCheckPermission(value = "system:role:add", orRole = "admin")
    public R<Void> create(@Valid @RequestBody RoleDTO roleDTO) {
        roleService.create(roleDTO);
        return R.ok();
    }

    @Operation(summary = "更新角色", description = "根据ID更新角色信息")
    @PutMapping
    @SaCheckPermission(value = "system:role:edit", orRole = "admin")
    public R<Void> update(@Valid @RequestBody RoleDTO roleDTO) {
        roleService.update(roleDTO);
        return R.ok();
    }

    @Operation(summary = "删除角色", description = "根据ID删除角色")
    @DeleteMapping("/{id}")
    @SaCheckPermission(value = "system:role:delete", orRole = "admin")
    public R<Void> delete(@Parameter(description = "角色ID") @PathVariable Long id) {
        roleService.delete(id);
        return R.ok();
    }

    @Operation(summary = "获取角色详情", description = "根据ID获取角色详细信息")
    @GetMapping("/{id}")
    @SaCheckPermission(value = "system:role:list", orRole = "admin")
    public R<Role> getById(@Parameter(description = "角色ID") @PathVariable Long id) {
        return R.ok(roleService.getById(id));
    }

    @Operation(summary = "检查角色编码是否存在", description = "检查角色编码是否已存在，用于创建和更新时的唯一性校验")
    @GetMapping("/check-code")
    @SaCheckPermission(value = "system:role:list", orRole = "admin")
    public R<Boolean> checkRoleCode(
            @Parameter(description = "角色编码") @RequestParam String roleCode,
            @Parameter(description = "排除的角色ID（更新时使用）") @RequestParam(required = false) Long excludeId) {
        return R.ok(roleService.checkRoleCodeExists(roleCode, excludeId));
    }

    @Operation(summary = "为角色分配用户", description = "为指定角色分配用户")
    @PostMapping("/assign-users")
    @SaCheckPermission(value = "system:role:edit", orRole = "admin")
    public R<Void> assignUsers(@Valid @RequestBody AssignUserDTO assignUserDTO) {
        roleService.assignUsers(assignUserDTO.getRoleId(), assignUserDTO.getUserIds());
        return R.ok();
    }

    @Operation(summary = "为角色分配权限", description = "为指定角色分配权限")
    @PostMapping("/assign-permissions")
    @SaCheckPermission(value = "system:role:edit", orRole = "admin")
    public R<Void> assignPermissions(@Valid @RequestBody AssignPermissionDTO assignPermissionDTO) {
        roleService.assignPermissions(assignPermissionDTO.getRoleId(), assignPermissionDTO.getPermissionIds());
        return R.ok();
    }

    @Operation(summary = "获取角色权限", description = "获取指定角色的权限")
    @GetMapping("/permissions/{roleId}")
    @SaCheckPermission(value = "system:role:list", orRole = "admin")
    public R<List<Long>> getRolePermissions(@Parameter(description = "角色ID") @PathVariable Long roleId) {
        return R.ok(roleService.getRolePermissions(roleId));
    }

    @Operation(summary = "获取权限树", description = "获取所有权限的树形结构")
    @GetMapping("/permissions/tree")
    @SaCheckPermission(value = "system:role:list", orRole = "admin")
    public R<List<SysPermission>> getPermissionTree() {
        return R.ok(permissionService.tree());
    }

    @Operation(summary = "获取角色用户", description = "获取指定角色的所有用户ID")
    @GetMapping("/users/{roleId}")
    @SaCheckPermission(value = "system:role:list", orRole = "admin")
    public R<List<Long>> getRoleUsers(@Parameter(description = "角色ID") @PathVariable Long roleId) {
        return R.ok(roleService.getRoleUsers(roleId));
    }
}
